package org.xx.armory.commons;

import java.math.BigDecimal;

/**
 * 用于对金额进行格式化的工具类。
 *
 * @author Haart
 */
public final class CurrencyFormatter {
    private static final String[] CURRENCY_DIGIT_HZ = {
            "\u96f6", "\u58f9", "\u8d30", "\u53c1", "\u8086",
            "\u4f0d", "\u9646", "\u67d2", "\u634c", "\u7396"};
    private static final String CURRENCY_HZ_YI = "\u4ebf";
    private static final String CURRENCY_HZ_WAN = "\u4e07";
    private static final String CURRENCY_HZ_QIAN = "\u4edf";
    private static final String CURRENCY_HZ_BAI = "\u4f70";
    private static final String CURRENCY_HZ_SHI = "\u62fe";
    private static final String CURRENCY_HZ_YUAN = "\u5143";
    private static final String CURRENCY_HZ_ZHEN = "\u6574";
    private static final String CURRENCY_HZ_JIAO = "\u89d2";
    private static final String CURRENCY_HZ_FEN = "\u5206";

    private static final String[] CURRENCY_DIGIT_HZ_UNIT = {
            CURRENCY_HZ_YUAN, CURRENCY_HZ_SHI, CURRENCY_HZ_BAI, CURRENCY_HZ_QIAN, CURRENCY_HZ_WAN,
            CURRENCY_HZ_SHI, CURRENCY_HZ_BAI, CURRENCY_HZ_QIAN, CURRENCY_HZ_YI,
            CURRENCY_HZ_SHI, CURRENCY_HZ_BAI, CURRENCY_HZ_QIAN, CURRENCY_HZ_WAN,
            CURRENCY_HZ_SHI, CURRENCY_HZ_BAI, CURRENCY_HZ_QIAN};

    private CurrencyFormatter() {
        throw new UnsupportedOperationException();
    }

    /**
     * 将金额转化为汉字大写格式。
     *
     * <p>
     * 比分更小的部分不会显示。
     * </p>
     *
     * @param m
     *         待转化的金额
     * @return 汉字大写形式, 如果参数{@code m}是{@code null}则返回空字符串({@code ""})。
     */
    public static String toHz(final BigDecimal m) {
        if (m == null) {
            return "";
        } else if (m.signum() == 0) {
            return CURRENCY_DIGIT_HZ[0] + CURRENCY_DIGIT_HZ_UNIT[0];
        }

        final StringBuilder sb = new StringBuilder();
        final int BUFFER_SIZE = 32;
        final int[] buffer = new int[BUFFER_SIZE];

        long l = m.longValue();
        if (l < 0)
            l = -l;

        if (l != 0) {
            // Integer value.
            int i = 0;
            while (l >= 10) {
                buffer[i++] = (int) (l % 10);
                l = l / 10;
            }
            buffer[i] = (int) l;

            boolean prevZero = false;
            for (; i >= 0; --i) {
                final int d = buffer[i];
                if (d == 0) {
                    if (i % 4 == 0) {
                        sb.append(CURRENCY_DIGIT_HZ_UNIT[i]);
                    }

                    prevZero = true;
                } else {
                    if (prevZero) {
                        sb.append(CURRENCY_DIGIT_HZ[0]);
                    }
                    sb.append(CURRENCY_DIGIT_HZ[d]);
                    sb.append(CURRENCY_DIGIT_HZ_UNIT[i]);
                    prevZero = false;
                }
            }
        }

        final long p1 = m.longValue() * 100;
        final long p2 = m.movePointRight(2).longValue();
        int mi = (int) (p2 > p1 ? p2 - p1 : p1 - p2);

        if (mi != 0) {
            final int jiao = mi / 10;
            final int fen = mi % 10;
            if (jiao != 0) {
                sb.append(CURRENCY_DIGIT_HZ[jiao]);
                sb.append(CURRENCY_HZ_JIAO);
            }
            if (fen != 0) {
                sb.append(CURRENCY_DIGIT_HZ[fen]);
                sb.append(CURRENCY_HZ_FEN);
            }
        } else {
            sb.append(CURRENCY_HZ_ZHEN);
        }

        // Decimal value.

        return sb.toString();
    }
}
